package com.itcs.se.security.service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.itcs.box.util.DateUtils;
import com.itcs.se.security.conf.SeConfig;
import com.itcs.se.security.data.req.Box1021Req;
import com.itcs.se.security.data.req.Box1022Req;
import com.itcs.se.security.data.req.Box1023Req;
import com.itcs.se.security.data.req.BoxDncryptReq;
import com.itcs.se.security.data.req.BoxEncryptReq;
import com.itcs.se.security.data.res.Box2021Res;
import com.itcs.se.security.data.res.Box2022Res;
import com.itcs.se.security.data.res.Box2023Res;
import com.itcs.se.security.data.res.BoxDncryptRes;
import com.itcs.se.security.data.res.BoxEncryptRes;
import com.itcs.se.security.domain.SeRelease;

import cn.tksspApi.exception.TKSSPAPIException;
import cn.tksspApi.mp.TResultSet;

/**
 * @ClassName: SeSecurityService
 * @Description:TODO(这里用一句话描述这个类的作用)
 * @author: CHEN-HF
 * @date: 2018年10月20日 上午11:17:56
 * 
 * @Copyright: 2018 Inc. All rights reserved. 注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目
 */
@Service
public class SeSecurityService {

	private Log logger = LogFactory.getLog(getClass());

	@Autowired
	private SeConfig seConfig;
	
	@Autowired
	private SeReleaseService seReleaseService;
	
	private Map<String, String> seReleaseMap = new HashMap<String, String>();

	// 发行请求验证
	public Box2021Res doIssueVerifyRequest(Box1021Req req) {
		Date startDate = new Date();
		logger.info("开始执行发行请求验证:" + JSON.toJSONString(req));
		try {
			logger.info("发行请求验证参数:" + req.getIssueRequestVerify());
			TResultSet rs = seConfig.getTCSSP().doIssueVerifyRequest(req.getIssueRequestVerify());
			
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行发行请求验证结果：" + rs.getErrCode() + ",设备:" + req.getSeSn() + "发行状态为：" + rs.getIssueStat());
			if (rs.getErrCode() == 0) {
				return new Box2021Res(String.valueOf(rs.getErrCode()), rs.getIssueStat()==null?null:rs.getIssueStat().toString());
			} else {
				return new Box2021Res(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new Box2021Res();
		} catch (Exception e) {
			return new Box2021Res();
		}
	}

	// 发行请求-贵州接口
	public Box2022Res doIssueRequestForGZ(Box1022Req req) {
		Date startDate = new Date();
		logger.info("开始执行发行请求" + JSON.toJSONString(req));
		try {
			logger.info("发行请求参数:" + req.getIssueReq());
			TResultSet rs = seConfig.getTCSSP().doIssueRequestForGZ(req.getIssueReq());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行发行请求结果：" + rs.getErrCode() + ",设备:" + req.getSeSn() + "结果值为：" + rs.getIssueData());
			if (rs.getErrCode() == 0) {
				if(!StringUtils.isEmpty(rs.getIssueData())){ //&rs.getIssueData().split("\\|").length==2
					return new Box2022Res(String.valueOf(rs.getErrCode()), rs.getIssueData().split("\\|")[0], rs.getIssueData().split("\\|")[1]);
				}else{
					return new Box2022Res(String.valueOf(rs.getErrCode()));
				}
			}else{
				return new Box2022Res(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new Box2022Res();
		} catch (Exception e) {
			return new Box2022Res();
		}
	}

	// 发行请求-北京接口
	public Box2022Res doIssueRequest1ForBJ(Box1022Req req) {
		Date startDate = new Date();
		logger.info("开始执行发行请求" + JSON.toJSONString(req));
		try {
			logger.info("发行请求参数:" + req.getIssueReq());
			TResultSet rs = seConfig.getTCSSP().doIssueRequest1ForBJ(req.getIssueReq());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行发行请求结果：" + rs.getErrCode() + ",设备:" + req.getSeSn() + "结果值为：" + rs.getIssueData());
			if (rs.getErrCode() == 0) {
				if(!StringUtils.isEmpty(rs.getIssueData())){ //&rs.getIssueData().split("\\|").length==2
					Box2022Res res = new Box2022Res("seWrite0015", rs.getIssueData().split("\\|")[0]);
					res.setErrCode(String.valueOf(rs.getErrCode()));
					return res;
				}else{
					return new Box2022Res(String.valueOf(rs.getErrCode()));
				}
			}else{
				return new Box2022Res(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new Box2022Res();
		} catch (Exception e) {
			return new Box2022Res();
		}
	}

	// 发行请求-北京接口
	public Box2022Res doIssueRequest2ForBJ(Box1022Req req) {
		Date startDate = new Date();
		logger.info("开始执行发行请求" + JSON.toJSONString(req));
		try {
			logger.info("发行请求参数:" + req.getIssueReq2ForBj());
			TResultSet rs = seConfig.getTCSSP().doIssueRequest2ForBJ(req.getIssueReq2ForBj());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行发行请求结果：" + rs.getErrCode() + ",设备:" + req.getSeSn() + "结果值为：" + rs.getIssueData());
			if (rs.getErrCode() == 0) {
				if(!StringUtils.isEmpty(rs.getIssueData())){ //&rs.getIssueData().split("\\|").length==2
					Box2022Res res = new Box2022Res("seWritePK", rs.getIssueData().split("\\|")[0]);
					res.setErrCode(String.valueOf(rs.getErrCode()));
					return res;
				}else{
					return new Box2022Res(String.valueOf(rs.getErrCode()));
				}
			}else{
				return new Box2022Res(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new Box2022Res();
		} catch (Exception e) {
			e.printStackTrace();
			return new Box2022Res();
		}
	}

	// 握手认证
	public Box2023Res doAuthenAndGenSessionKey(Box1023Req req) {
		Date startDate = new Date();
		logger.info("开始执行握手认证" + JSON.toJSONString(req));
		try {
			logger.info("行握手认证参数:" + req.getIssueReq());
			TResultSet rs = seConfig.getTCSSP().doAuthenAndGenSessionKey(req.getIssueReq());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行发行请求结果：" + rs.getErrCode() + ",设备:" + req.getSeSn() + "结果值为：" + rs.getAuthAnsData());
			if (rs.getErrCode() == 0) {
				if(!StringUtils.isEmpty(rs.getAuthAnsData())){ //&rs.getAuthAnsData().split("\\|").length==7
					String[] rsData = rs.getAuthAnsData().split("\\|");
					Box2023Res res = new Box2023Res(String.valueOf(rs.getErrCode()));
					res.setSeTTL(rsData[0]);
					res.setSeK1Enc(rsData[1]);
					res.setSeK1Mac(rsData[2]);
					res.setSeK2Enc(rsData[3]);
					res.setSeK2Mac(rsData[4]);
					res.setSeR(rsData[5]);
					res.setSeS2(rsData[6]);
					
					seReleaseMap.put(req.getClientId(), req.getSeSn());
					this.save(req); //保存数据库
					return res;
				}else{
					return new Box2023Res(String.valueOf(rs.getErrCode()));
				}
			} else {
				return new Box2023Res(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new Box2023Res();
		} catch (Exception e) {
			return new Box2023Res();
		}

	}

	// 工作密钥加密
	public BoxEncryptRes doEncryptWithSessionKey(BoxEncryptReq req) {
		Date startDate = new Date();
		logger.info("开始执行工作密钥加密" + JSON.toJSONString(req));
		try {
			TResultSet rs = seConfig.getTCSSP().doEncryptWithSessionKey(this.getSn(req.getClientId()), req.getPlaintext().getBytes(), req.getEncType());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行工作密钥加密：" + rs.getErrCode());
			
			if (rs.getErrCode() == 0) {
				logger.info("加密后字符Ciphertext: [" + rs.getCipherText() + "]");
				if (rs.getCipherMac() != null) {
					logger.info("加密后生成MAC Ciphermac: [" + rs.getCipherMac() + "]");
				}
				return new BoxEncryptRes(String.valueOf(rs.getErrCode()), rs.getCipherText(), rs.getCipherMac());
			} else {
				return new BoxEncryptRes(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new BoxEncryptRes();
		} catch (Exception e) {
			return new BoxEncryptRes();
		}

	}

	// 工作密钥解密
	public BoxDncryptRes doDecryptWithSessionKey(BoxDncryptReq req) {
		Date startDate = new Date();
		logger.info("开始执行工作密钥解密" + JSON.toJSONString(req));
		try {
			TResultSet rs = seConfig.getTCSSP().doDecryptWithSessionKey(this.getSn(req.getClientId()), 0, req.getCipherText(),
					req.getCipherMac());
			Date endDate = new Date();
			logger.info("耗时" + ((endDate.getTime() - startDate.getTime())) + "毫秒,执行工作密钥解密：" + rs.getErrCode());

			if (rs.getErrCode() == 0) {
				logger.info("解密后字符Plaintext: [" + new String(rs.getPlainText(), "UTF-8") + "]");
				// return new BoxDncryptRes(DataConverter.bytesToHexString(rs.getPlainText()));
				return new BoxDncryptRes(new String(rs.getPlainText(), "UTF-8"));
			} else {
				return new BoxDncryptRes(String.valueOf(rs.getErrCode()));
			}
		} catch (TKSSPAPIException e) {
			callTcsspWaring(e);
			return new BoxDncryptRes();
		} catch (Exception e) {
			return new BoxDncryptRes();
		}
	}
	
	private void callTcsspWaring(TKSSPAPIException e) {
		logger.warn("调用密码安全服务系统失败:" + e.getMessage());
	}
	
	// 根据绑定客户端获取sn
	private String getSn(String clientId) {
//		if (!StringUtils.isEmpty(seReleaseMap.get(clientId))) {
//			return seReleaseMap.get(clientId);
//		} else {
			SeRelease se = seReleaseService.getSeReleaseWithOne(new String[] { "clientId" }, new Object[] { clientId });
			if (!StringUtils.isEmpty(se.getSn())) {
				seReleaseMap.put(clientId, se.getSn());
				return se.getSn();
			} else {
				return "";
			}
//		}
	}
	
	// 启用数据库存储
	private void save(Box1023Req req) {
		SeRelease se = seReleaseService.getSeReleaseWithOne(new String[] { "clientId" }, new Object[] { req.getClientId() });
		// 写入数据库
		if (se == null) {
			se = new SeRelease();
			se.setCreateTime(DateUtils.getToday("yyyy-MM-dd HH:mm:ss"));
		}
		se.setClientId(req.getClientId());
		se.setSn(req.getSeSn());
		se.setUpdateTime(DateUtils.getToday("yyyy-MM-dd HH:mm:ss"));
		seReleaseService.saveOrUpdateSeRelease(se);
	}

}
